package com.geline.sqlbackup.druid;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.geline.sqlbackup.bean.ColumnInfo;
import com.geline.sqlbackup.bean.TableColumnInfo;
import com.geline.sqlbackup.enums.HtmlTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * DDL-sql解析处理器
 * @author mengx
 * @date 2020/12/27 10:22
 */
public interface DdlSqlHandler {
    static final Logger log = LoggerFactory.getLogger(DdlSqlHandler.class);

    public TableColumnInfo handler(String ddlSql, List<String> ignoredColumnList, boolean useRemoveTableHead, boolean useCamelCase);

    /**
     * 处理 create table
     * @param cstmt
     * @return
     */
    public default List<ColumnInfo> initColumnInfoList(SQLCreateTableStatement cstmt, List<String> ignoredColumnList, boolean useCamelCase) {
        List<ColumnInfo> columnInfoList = new ArrayList<>();

        //解析字段信息
        List<SQLColumnDefinition> columnDefinitions = cstmt.getColumnDefinitions();
        columnDefinitions.stream().forEach(definition -> {
            //字段名称
            String columnName = definition.getColumnName();
            String columnSimpleName = definition.getColumnName().replaceAll("\"|'|`|\\[|]", "");
            if(ignoredColumnList!=null && ignoredColumnList.contains(columnName)){
                return;
            }

            //字段注释 oracle字段需要单独解析
            SQLExpr comment = definition.getComment();
            String columnComment = comment==null ? "" : ((SQLCharExpr)comment).getText();

            //字段类型
            SQLDataType sqlDataType = definition.getDataType();
            String dataType = sqlDataType.getName();

            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setColumnName(columnName);
            columnInfo.setColumnComment(columnComment);
            columnInfo.setDefaultValue("");
            columnInfo.setColumnType(dataType);
            Integer vendorTypeNumber = getVendorTypeNumber(columnName, dataType);
            columnInfo.setJdbcTypeCode(vendorTypeNumber);
            //首字母小写，转驼峰命名
            if(useCamelCase){
                columnInfo.setJavaFieldName(StrUtil.toCamelCase(StrUtil.lowerFirst(columnSimpleName)));
            }else {
                columnInfo.setJavaFieldName(StrUtil.lowerFirst(columnSimpleName));
            }

            //解析字段（10,2）内的长度信息
            List<SQLExpr> arguments = sqlDataType.getArguments();
            if(arguments.size() > 0){
                String arg1 = arguments.get(0).toString();
                if(NumberUtil.isInteger(arg1)){
                    columnInfo.setLength(Integer.valueOf(arg1));
                }
                if(arguments.size() > 1){
                    String arg2 = arguments.get(1).toString();
                    if(NumberUtil.isInteger(arg2)){
                        columnInfo.setScale(Integer.valueOf(arg2));
                    }
                }
            }

            boolean notNull = definition.containsNotNullConstaint();
            boolean primaryKey = definition.isPrimaryKey();
            boolean autoIncrement = definition.isAutoIncrement();

            columnInfo.setJavaFieldType(this.getJavaType(columnSimpleName, dataType));
            columnInfo.setNotNull(notNull);
            columnInfo.setPrimaryKey(primaryKey);
            columnInfo.setAutoIncrement(autoIncrement);
            //设置字段是否为日期类型，用于默认排序
            columnInfo.setDateTypeFlag(StrUtil.equalsAnyIgnoreCase(dataType, "year", "date", "datetime", "timestamp"));
            columnInfo.setIntFlag(sqlDataType.isInt());
            columnInfo.setNumbericFlag(sqlDataType.isNumberic());
            columnInfo.setStringFlag(sqlDataType.isString());

            if(dataType.equalsIgnoreCase("datetime") || dataType.equalsIgnoreCase("timestamp")){
                columnInfo.setHtmlTypeEnum(HtmlTypeEnum.DATETIME);
            }else if(dataType.equalsIgnoreCase("date")){
                columnInfo.setHtmlTypeEnum(HtmlTypeEnum.DATE);
            }else if(dataType.equalsIgnoreCase("time")){
                columnInfo.setHtmlTypeEnum(HtmlTypeEnum.TIME);
            }else if(sqlDataType.isString()){
                if(columnInfo.getLength()==null || columnInfo.getLength()>255){
                    columnInfo.setHtmlTypeEnum(HtmlTypeEnum.TEXTAREA);
                }else {
                    columnInfo.setHtmlTypeEnum(HtmlTypeEnum.TEXT);
                }
            }else if(sqlDataType.isInt() || sqlDataType.isNumberic()){
                Integer length = columnInfo.getLength();
                if(primaryKey || length>11){
                    //如果数字类型，且长度>11设置为input:text；如　bigint(20)
                    columnInfo.setHtmlTypeEnum(HtmlTypeEnum.TEXT);
                }else {
                    columnInfo.setHtmlTypeEnum(HtmlTypeEnum.NUMBER);
                }
            }else {
                columnInfo.setHtmlTypeEnum(HtmlTypeEnum.TEXT);
            }
            columnInfoList.add(columnInfo);
            //logger.debug(String.format(">>>>> %s - %s - %s - PK=%s - autoIncrement=%s, notNull=%s", columnName, columnComment, dataType, primaryKey, autoIncrement, notNull));
        });
        return columnInfoList;
    }

    public SchemaStatVisitor initSchemaStatVisitor();

    public Integer getVendorTypeNumber(String columnName, String dataType);

    public String getJavaType(String columnName, String dataType);
}
